/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * NewJFrame.java
 *
 * Created on Nov 14, 2010, 2:35:36 PM
 */
package dataclustering;

import java.awt.Cursor;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.Scanner;
import java.util.Vector;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import javax.swing.filechooser.FileFilter;

/**
 *
 * @author Thuan Loc
 */
public class MainFrame extends javax.swing.JFrame implements ActionListener, PropertyChangeListener {

    Vector<Point3D> VP;
    private Task task;
    private File FR;

    private void hideStatus() {
        this.jLabelStatus.setVisible(false);
        this.jLabelSizeOfFileName.setVisible(false);
        this.jLabelNumOfOName.setVisible(false);
        this.jLabelNofO.setVisible(false);
        this.jLabelSizeofF.setVisible(false);
        this.jLabelSizeOfFileName.setVisible(false);
    }

    class Task extends SwingWorker<Void, Void> {
        /*
         * Main task. Executed in background thread.
         */

        @Override
        public Void doInBackground() {
            int progress = 0;
            //Initialize progress property.
            setProgress(0);
            try {
                Scanner in = new Scanner(FR);
                long len = 0;
                for (int i = 0; i < 12; i++) {
                    len += (in.next().length() + 1);
                }
                while (in.hasNext()) {
                    String s = in.next();
                    len += (s.length() + 1);
                    String[] SP = s.split(",");
                    VP.add(new Point3D(Double.parseDouble(SP[0]), Double.parseDouble(SP[1]), Double.parseDouble(SP[2])));
                    progress = (int) ((double) len / (double) FR.length() * 100);
                    setProgress(progress);
                }
                setProgress(100);
            } catch (Exception e) {
            }
            return null;
        }

        /**
         * Invoked when task's progress property changes.
         */
        public void propertyChange(PropertyChangeEvent evt) {
            if (evt.getPropertyName().compareTo("progress") == 0) {
                int progress = (Integer) evt.getNewValue();
                jProgressBarTestFile.setValue(progress);
            }
        }

        /*
         * Executed in event dispatching thread
         */
        @Override
        public void done() {
            Toolkit.getDefaultToolkit().beep();
            if (VP.isEmpty()) {
                jLabelStatus.setText("Please choose an .arff file");
                jLabelStatus.setVisible(true);
                jButtonTestFile.setEnabled(true);
            } else {
                jLabelSizeofF.setText(Long.toString(FR.length() / 1024) + "KB");
                jLabelNofO.setText(Integer.toString(VP.size()));
                jButtonTestFile.setEnabled(true);
                jLabelStatus.setText("Status");
                jLabelStatus.setVisible(true);
                jLabelSizeOfFileName.setVisible(true);
                jLabelNumOfOName.setVisible(true);
                jLabelNofO.setVisible(true);
                jLabelSizeofF.setVisible(true);
                jLabelSizeOfFileName.setVisible(true);
                jTextFieldClusterNumber.setEditable(true);
                if (!jRadioButtonMenuItemEM.isSelected()) {
                    jTextFieldIterations.setEditable(true);
                    
                }
            }
            setCursor(null); //turn off the wait cursor
        }
    }

    /** Creates new form NewJFrame */
    public MainFrame() {
        initComponents();
        VP = new Vector<Point3D>();
        this.jTabbedPane.remove(1);
        this.jTextFieldClusterNumber.setEditable(false);
        this.jTextFieldIterations.setEditable(false);
        this.ClusteringPanelChart.plotToolBar.setVisible(false);
        this.hideStatus();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        buttonGroup1 = new javax.swing.ButtonGroup();
        buttonGroup2 = new javax.swing.ButtonGroup();
        jTabbedPane = new javax.swing.JTabbedPane();
        jPanelSpecification = new javax.swing.JPanel();
        jTextFieldClusterNumber = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();
        jSeparator1 = new javax.swing.JSeparator();
        jButtonAnalysis = new javax.swing.JButton();
        jLabel3 = new javax.swing.JLabel();
        jTextFieldFileChoice = new javax.swing.JTextField();
        jButtonBrowse = new javax.swing.JButton();
        jButtonTestFile = new javax.swing.JButton();
        jLabelSizeOfFileName = new javax.swing.JLabel();
        jLabelStatus = new javax.swing.JLabel();
        jLabelNumOfOName = new javax.swing.JLabel();
        jLabelSizeofF = new javax.swing.JLabel();
        jLabelNofO = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel11 = new javax.swing.JLabel();
        jRadioButtonEuclidean = new javax.swing.JRadioButton();
        jRadioButtonManhattan = new javax.swing.JRadioButton();
        jLabelDistanceMeasureDiscription = new javax.swing.JLabel();
        jLabel1DistanceFormula = new javax.swing.JLabel();
        jProgressBarTestFile = new javax.swing.JProgressBar();
        jPanel2 = new javax.swing.JPanel();
        jLabel12 = new javax.swing.JLabel();
        jTextFieldIterations = new javax.swing.JTextField();
        jPanelPerformance = new javax.swing.JPanel();
        ClusteringPanelChart = new org.math.plot.Plot3DPanel();
        jPanel1 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        jButton2 = new javax.swing.JButton();
        jLabel4 = new javax.swing.JLabel();
        jMenuBar = new javax.swing.JMenuBar();
        jMenuAlgorithm = new javax.swing.JMenu();
        jRadioButtonMenuItemBasicKMeans = new javax.swing.JRadioButtonMenuItem();
        jSeparatorAlgorithm = new javax.swing.JPopupMenu.Separator();
        jRadioButtonMenuItemKMedoids = new javax.swing.JRadioButtonMenuItem();
        jRadioButtonMenuItemBisectingKMeans = new javax.swing.JRadioButtonMenuItem();
        jRadioButtonMenuItemEM = new javax.swing.JRadioButtonMenuItem();
        jMenuHelp = new javax.swing.JMenu();
        jSeparatorHelp = new javax.swing.JPopupMenu.Separator();
        jMenuItemAbout = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("K-Means Paradigm");
        setBounds(new java.awt.Rectangle(55, 45, 50, 50));

        jTextFieldClusterNumber.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N

        jLabel1.setFont(new java.awt.Font("Tahoma", 0, 14));
        jLabel1.setText("Number of Clusters");

        jSeparator1.setOrientation(javax.swing.SwingConstants.VERTICAL);

        jButtonAnalysis.setFont(new java.awt.Font("Tahoma", 0, 14));
        jButtonAnalysis.setText("Analyze");
        jButtonAnalysis.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonAnalysisActionPerformed(evt);
            }
        });

        jLabel3.setFont(new java.awt.Font("Tahoma", 0, 14));
        jLabel3.setText("Choose a sample file (*.arff)");

        jTextFieldFileChoice.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
        jTextFieldFileChoice.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jTextFieldFileChoiceActionPerformed(evt);
            }
        });

        jButtonBrowse.setText("Browse");
        jButtonBrowse.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonBrowseActionPerformed(evt);
            }
        });

        jButtonTestFile.setText("Test File");
        jButtonTestFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonTestFileActionPerformed(evt);
            }
        });

        jLabelSizeOfFileName.setFont(new java.awt.Font("Tahoma", 0, 16)); // NOI18N
        jLabelSizeOfFileName.setText("Size of file");

        jLabelStatus.setFont(new java.awt.Font("Tahoma", 0, 18));
        jLabelStatus.setText("Status");

        jLabelNumOfOName.setFont(new java.awt.Font("Tahoma", 0, 16));
        jLabelNumOfOName.setText("Number of objects");

        jLabelSizeofF.setFont(new java.awt.Font("Tahoma", 0, 16)); // NOI18N
        jLabelSizeofF.setText("N/A");

        jLabelNofO.setFont(new java.awt.Font("Tahoma", 0, 16));
        jLabelNofO.setText("N/A");

        jLabel2.setFont(new java.awt.Font("Tahoma", 0, 12));
        jLabel2.setText("( *Positive integer less or equal to N)");

        jLabel11.setFont(new java.awt.Font("Tahoma", 0, 14));
        jLabel11.setText("Distance Measures");

        buttonGroup2.add(jRadioButtonEuclidean);
        jRadioButtonEuclidean.setFont(new java.awt.Font("Tahoma", 0, 12));
        jRadioButtonEuclidean.setSelected(true);
        jRadioButtonEuclidean.setText("Euclidean");
        jRadioButtonEuclidean.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jRadioButtonEuclideanActionPerformed(evt);
            }
        });

        buttonGroup2.add(jRadioButtonManhattan);
        jRadioButtonManhattan.setFont(new java.awt.Font("Tahoma", 0, 12));
        jRadioButtonManhattan.setText("Manhattan");
        jRadioButtonManhattan.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jRadioButtonManhattanActionPerformed(evt);
            }
        });

        jLabelDistanceMeasureDiscription.setText("The most popular distance measure which is defined as");

        jLabel1DistanceFormula.setIcon(new javax.swing.ImageIcon("C:\\Users\\Thuan Loc\\Documents\\NetBeansProjects\\Data Clustering\\Picture\\Euclidean_Distance.png")); // NOI18N

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Additional Configuration", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 1, 12))); // NOI18N

        jLabel12.setFont(new java.awt.Font("Tahoma", 0, 12));
        jLabel12.setText("Maximum number of iterations");

        jTextFieldIterations.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel12)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 38, Short.MAX_VALUE)
                .addComponent(jTextFieldIterations, javax.swing.GroupLayout.PREFERRED_SIZE, 158, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(32, 32, 32))
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addGap(28, 28, 28)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel12)
                    .addComponent(jTextFieldIterations, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(27, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout jPanelSpecificationLayout = new javax.swing.GroupLayout(jPanelSpecification);
        jPanelSpecification.setLayout(jPanelSpecificationLayout);
        jPanelSpecificationLayout.setHorizontalGroup(
            jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelSpecificationLayout.createSequentialGroup()
                .addGap(35, 35, 35)
                .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel3)
                    .addComponent(jLabelSizeOfFileName, javax.swing.GroupLayout.PREFERRED_SIZE, 105, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabelNumOfOName, javax.swing.GroupLayout.PREFERRED_SIZE, 165, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(jPanelSpecificationLayout.createSequentialGroup()
                            .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                .addComponent(jTextFieldFileChoice, javax.swing.GroupLayout.PREFERRED_SIZE, 294, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(jProgressBarTestFile, javax.swing.GroupLayout.DEFAULT_SIZE, 294, Short.MAX_VALUE))
                            .addGap(18, 18, 18)
                            .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                .addComponent(jButtonTestFile, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(jButtonBrowse, javax.swing.GroupLayout.DEFAULT_SIZE, 76, Short.MAX_VALUE)))
                        .addComponent(jLabelStatus, javax.swing.GroupLayout.DEFAULT_SIZE, 388, Short.MAX_VALUE))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanelSpecificationLayout.createSequentialGroup()
                        .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(jLabelNofO, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jLabelSizeofF, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 126, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGap(113, 113, 113)))
                .addGap(35, 35, 35)
                .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(45, 45, 45)
                .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                        .addComponent(jLabel1DistanceFormula, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(jLabelDistanceMeasureDiscription, javax.swing.GroupLayout.PREFERRED_SIZE, 389, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addComponent(jLabel11)
                        .addComponent(jLabel2)
                        .addGroup(jPanelSpecificationLayout.createSequentialGroup()
                            .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(jLabel1)
                                .addGroup(jPanelSpecificationLayout.createSequentialGroup()
                                    .addGap(68, 68, 68)
                                    .addComponent(jRadioButtonEuclidean)))
                            .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addGroup(jPanelSpecificationLayout.createSequentialGroup()
                                    .addGap(55, 55, 55)
                                    .addComponent(jRadioButtonManhattan))
                                .addGroup(jPanelSpecificationLayout.createSequentialGroup()
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(jTextFieldClusterNumber, javax.swing.GroupLayout.PREFERRED_SIZE, 96, javax.swing.GroupLayout.PREFERRED_SIZE))))
                        .addComponent(jButtonAnalysis, javax.swing.GroupLayout.PREFERRED_SIZE, 87, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addGap(45, 45, 45))
        );
        jPanelSpecificationLayout.setVerticalGroup(
            jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelSpecificationLayout.createSequentialGroup()
                .addGap(46, 46, 46)
                .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanelSpecificationLayout.createSequentialGroup()
                        .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(jLabel3)
                                .addComponent(jTextFieldFileChoice, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addComponent(jButtonBrowse))
                        .addGap(87, 87, 87)
                        .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addComponent(jProgressBarTestFile, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(jButtonTestFile, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addGap(64, 64, 64)
                        .addComponent(jLabelStatus)
                        .addGap(54, 54, 54)
                        .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabelSizeOfFileName)
                            .addComponent(jLabelSizeofF))
                        .addGap(41, 41, 41)
                        .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jLabelNumOfOName)
                            .addComponent(jLabelNofO)))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanelSpecificationLayout.createSequentialGroup()
                        .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(jSeparator1, javax.swing.GroupLayout.DEFAULT_SIZE, 547, Short.MAX_VALUE)
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanelSpecificationLayout.createSequentialGroup()
                                .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                    .addComponent(jLabel1)
                                    .addComponent(jTextFieldClusterNumber, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(jLabel2)
                                .addGap(28, 28, 28)
                                .addComponent(jLabel11)
                                .addGap(19, 19, 19)
                                .addGroup(jPanelSpecificationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                    .addComponent(jRadioButtonEuclidean)
                                    .addComponent(jRadioButtonManhattan))
                                .addGap(24, 24, 24)
                                .addComponent(jLabelDistanceMeasureDiscription)
                                .addGap(18, 18, 18)
                                .addComponent(jLabel1DistanceFormula)
                                .addGap(70, 70, 70)
                                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(76, 76, 76)
                                .addComponent(jButtonAnalysis, javax.swing.GroupLayout.PREFERRED_SIZE, 48, javax.swing.GroupLayout.PREFERRED_SIZE)))
                        .addGap(27, 27, 27))))
        );

        jTabbedPane.addTab("Specification", jPanelSpecification);

        jTable1.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null, null},
                {null, null, null, null, null},
                {null, null, null, null, null},
                {null, null, null, null, null},
                {null, null, null, null, null}
            },
            new String [] {
                "Cluster No", "NOf Objects", "Centroid's X", "Centroid's Y", "Centroid's Z"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.Integer.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class, java.lang.Object.class
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }
        });
        jScrollPane1.setViewportView(jTable1);

        jButton2.setFont(new java.awt.Font("Tahoma", 0, 14));
        jButton2.setText("Stop");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });

        jLabel4.setFont(new java.awt.Font("Tahoma", 0, 14));
        jLabel4.setForeground(new java.awt.Color(255, 0, 0));
        jLabel4.setText("Please wait...");

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
                        .addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 98, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 151, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 403, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 553, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton2, javax.swing.GroupLayout.DEFAULT_SIZE, 48, Short.MAX_VALUE)
                    .addComponent(jLabel4, javax.swing.GroupLayout.DEFAULT_SIZE, 48, Short.MAX_VALUE))
                .addContainerGap())
        );

        javax.swing.GroupLayout jPanelPerformanceLayout = new javax.swing.GroupLayout(jPanelPerformance);
        jPanelPerformance.setLayout(jPanelPerformanceLayout);
        jPanelPerformanceLayout.setHorizontalGroup(
            jPanelPerformanceLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanelPerformanceLayout.createSequentialGroup()
                .addComponent(ClusteringPanelChart, javax.swing.GroupLayout.PREFERRED_SIZE, 720, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanelPerformanceLayout.setVerticalGroup(
            jPanelPerformanceLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(ClusteringPanelChart, javax.swing.GroupLayout.DEFAULT_SIZE, 620, Short.MAX_VALUE)
            .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        jTabbedPane.addTab("Performance", jPanelPerformance);

        jMenuAlgorithm.setText("Algorithms");

        buttonGroup1.add(jRadioButtonMenuItemBasicKMeans);
        jRadioButtonMenuItemBasicKMeans.setSelected(true);
        jRadioButtonMenuItemBasicKMeans.setText("Basic K-Means");
        jRadioButtonMenuItemBasicKMeans.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jRadioButtonMenuItemBasicKMeansActionPerformed(evt);
            }
        });
        jMenuAlgorithm.add(jRadioButtonMenuItemBasicKMeans);
        jMenuAlgorithm.add(jSeparatorAlgorithm);

        buttonGroup1.add(jRadioButtonMenuItemKMedoids);
        jRadioButtonMenuItemKMedoids.setText("K-Medoids");
        jRadioButtonMenuItemKMedoids.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jRadioButtonMenuItemKMedoidsActionPerformed(evt);
            }
        });
        jMenuAlgorithm.add(jRadioButtonMenuItemKMedoids);

        buttonGroup1.add(jRadioButtonMenuItemBisectingKMeans);
        jRadioButtonMenuItemBisectingKMeans.setText("Bisecting K-Means");
        jRadioButtonMenuItemBisectingKMeans.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jRadioButtonMenuItemBisectingKMeansActionPerformed(evt);
            }
        });
        jMenuAlgorithm.add(jRadioButtonMenuItemBisectingKMeans);

        buttonGroup1.add(jRadioButtonMenuItemEM);
        jRadioButtonMenuItemEM.setText("Expectation Maximization (EM)");
        jRadioButtonMenuItemEM.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jRadioButtonMenuItemEMActionPerformed(evt);
            }
        });
        jMenuAlgorithm.add(jRadioButtonMenuItemEM);

        jMenuBar.add(jMenuAlgorithm);

        jMenuHelp.setText("Help");
        jMenuHelp.add(jSeparatorHelp);

        jMenuItemAbout.setText("About");
        jMenuItemAbout.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemAboutActionPerformed(evt);
            }
        });
        jMenuHelp.add(jMenuItemAbout);

        jMenuBar.add(jMenuHelp);

        setJMenuBar(jMenuBar);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jTabbedPane, javax.swing.GroupLayout.DEFAULT_SIZE, 1144, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jTabbedPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 648, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private int ensureClusterNumber() {
        String s = this.jTextFieldClusterNumber.getText();
        if (s.length() == 0 || s.length() > 9) {
            JOptionPane.showMessageDialog(this, "Number of Clusters is invalid");
            return -1;
        }

        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) < '0' || s.charAt(i) > '9') {
                JOptionPane.showMessageDialog(this, "Number of Clusters is invalid");
                return -1;
            }
        }

        int K = Integer.parseInt(s);
        if (K == 0 || K > this.VP.size()) {
            JOptionPane.showMessageDialog(this, "Number of Clusters is invalid");
            return -1;
        }
        return K;
    }

    private int ensureIterations() {
        String s = this.jTextFieldIterations.getText();
        if (s.length() == 0) {
            return 1000000000;
        }

        if (s.length() > 9) {
            JOptionPane.showMessageDialog(this, "Number of Interations is not valid");
            return -1;
        }

        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) < '0' || s.charAt(i) > '9') {
                JOptionPane.showMessageDialog(this, "Number of Interations is invalid");
                return -1;
            }
        }

        int MaxLoops = Integer.parseInt(s);
        if (MaxLoops == 0 || MaxLoops > this.VP.size()) {
            JOptionPane.showMessageDialog(this, "Number of Interations is invalid");
            return -1;
        }

        return MaxLoops;
    }
    /**
     * Invoked when task's progress property changes.
     */
    public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().compareTo("progress") == 0) {
            int progress = (Integer) evt.getNewValue();
            jProgressBarTestFile.setValue(progress);
        }
    }

    private void jRadioButtonMenuItemEMActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButtonMenuItemEMActionPerformed
        // TODO add your handling code here:
        this.jTextFieldIterations.setEditable(false);
        this.jTextFieldIterations.setText(null);
        this.jRadioButtonManhattan.setEnabled(false);
        this.jRadioButtonEuclidean.setSelected(true);
        jLabelDistanceMeasureDiscription.setText("The most popular distance measure which is defined as");
        jLabel1DistanceFormula.setIcon(new javax.swing.ImageIcon("C:\\Users\\Thuan Loc\\Documents\\NetBeansProjects\\Data Clustering\\Picture\\Euclidean_Distance.png"));
    }//GEN-LAST:event_jRadioButtonMenuItemEMActionPerformed

    private void jRadioButtonMenuItemBasicKMeansActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButtonMenuItemBasicKMeansActionPerformed
        // TODO add your handling code here:
        this.jTextFieldIterations.setEditable(true);
        this.jRadioButtonManhattan.setEnabled(true);
        this.jRadioButtonEuclidean.setSelected(true);
        jLabelDistanceMeasureDiscription.setText("The most popular distance measure which is defined as");
        jLabel1DistanceFormula.setIcon(new javax.swing.ImageIcon("C:\\Users\\Thuan Loc\\Documents\\NetBeansProjects\\Data Clustering\\Picture\\Euclidean_Distance.png"));
    }//GEN-LAST:event_jRadioButtonMenuItemBasicKMeansActionPerformed

    private void jRadioButtonMenuItemKMedoidsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButtonMenuItemKMedoidsActionPerformed
        // TODO add your handling code here:
        this.jTextFieldIterations.setEditable(true);
        this.jRadioButtonManhattan.setEnabled(true);
        this.jRadioButtonEuclidean.setSelected(true);
        jLabelDistanceMeasureDiscription.setText("The most popular distance measure which is defined as");
        jLabel1DistanceFormula.setIcon(new javax.swing.ImageIcon("C:\\Users\\Thuan Loc\\Documents\\NetBeansProjects\\Data Clustering\\Picture\\Euclidean_Distance.png"));
    }//GEN-LAST:event_jRadioButtonMenuItemKMedoidsActionPerformed

    private void jRadioButtonMenuItemBisectingKMeansActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButtonMenuItemBisectingKMeansActionPerformed
        // TODO add your handling code here:
        this.jTextFieldIterations.setEditable(true);
        this.jRadioButtonManhattan.setEnabled(true);
        this.jRadioButtonEuclidean.setSelected(true);
        jLabelDistanceMeasureDiscription.setText("The most popular distance measure which is defined as");
        jLabel1DistanceFormula.setIcon(new javax.swing.ImageIcon("C:\\Users\\Thuan Loc\\Documents\\NetBeansProjects\\Data Clustering\\Picture\\Euclidean_Distance.png"));
    }//GEN-LAST:event_jRadioButtonMenuItemBisectingKMeansActionPerformed

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
        // TODO add your handling code here:
        CONST.STOP = true;
        this.jLabel4.setVisible(true);
        this.jButton2.setEnabled(false);
}//GEN-LAST:event_jButton2ActionPerformed

    private void jRadioButtonManhattanActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButtonManhattanActionPerformed
        // TODO add your handling code here:
        jLabelDistanceMeasureDiscription.setText("A pseudonym is city block distance, which is defined as");
        jLabel1DistanceFormula.setIcon(new javax.swing.ImageIcon("C:\\Users\\Thuan Loc\\Documents\\NetBeansProjects\\Data Clustering\\Picture\\Manhattan_Distance.png"));
}//GEN-LAST:event_jRadioButtonManhattanActionPerformed

    private void jRadioButtonEuclideanActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jRadioButtonEuclideanActionPerformed
        // TODO add your handling code here:
        jLabelDistanceMeasureDiscription.setText("The most popular distance measure which is defined as");
        jLabel1DistanceFormula.setIcon(new javax.swing.ImageIcon("C:\\Users\\Thuan Loc\\Documents\\NetBeansProjects\\Data Clustering\\Picture\\Euclidean_Distance.png"));
}//GEN-LAST:event_jRadioButtonEuclideanActionPerformed

    private void jButtonTestFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonTestFileActionPerformed
        // TODO add your handling code here:
        try {
            hideStatus();
            this.VP.removeAllElements();
            jProgressBarTestFile.setValue(0);
            jProgressBarTestFile.setStringPainted(true);
            this.jButtonTestFile.setEnabled(false);
            setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
            //Instances of javax.swing.SwingWorker are not reusuable, so
            //we create new instances as needed.
            FR = new File(this.jTextFieldFileChoice.getText());
            task = new Task();
            task.addPropertyChangeListener(this);
            task.execute();
        } catch (Exception e) {
        }
    }//GEN-LAST:event_jButtonTestFileActionPerformed

    private void jButtonBrowseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonBrowseActionPerformed
        // TODO add your handling code here:
        FileFilter filter = new ExtensionFileFilter("*.arff", new String[]{"arff"});
        JFileChooser fileChooser = new JFileChooser();
        // Note: source for ExampleFileFilter can be found in FileChooserDemo,
        // under the demo/jfc directory in the Java 2 SDK, Standard Edition
        fileChooser.setFileFilter(filter);
        int status = fileChooser.showOpenDialog(null);
        if (status == JFileChooser.APPROVE_OPTION) {
            File selectedFile = fileChooser.getSelectedFile();
            this.jTextFieldFileChoice.setText(selectedFile.getAbsolutePath());
        }
}//GEN-LAST:event_jButtonBrowseActionPerformed

    private void jTextFieldFileChoiceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextFieldFileChoiceActionPerformed
        // TODO add your handling code here:
}//GEN-LAST:event_jTextFieldFileChoiceActionPerformed

    private void jButtonAnalysisActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonAnalysisActionPerformed
        // TODO add your handling code here:
        CONST.STOP = false;
        this.jTabbedPane.addTab("Performance", this.jPanelPerformance);
        this.jButton2.setEnabled(true);
        this.jLabel4.setVisible(false);

        int K = ensureClusterNumber();
        int MaxLoops = ensureIterations();

        if (K == -1 || MaxLoops == -1) {
            return;
        }
        this.jTabbedPane.setSelectedIndex(1);
        this.jTabbedPane.setEnabledAt(0, false);

        int DistanceType = CONST.EUCLIDEAN;
        if (this.jRadioButtonManhattan.isSelected()) {
            DistanceType = CONST.MANHATTAN;
        }

        if (this.jRadioButtonMenuItemBasicKMeans.isSelected()) {
            Thread thread = new ChartThread(CONST.BASIC_KMEANS, this.VP, K, MaxLoops, this.ClusteringPanelChart, this.jTable1, jLabel4, jButton2, jTabbedPane, DistanceType);
            thread.start();
        } else if (this.jRadioButtonMenuItemBisectingKMeans.isSelected()) {
            Thread thread = new ChartThread(CONST.BISECTING_KMEANS, this.VP, K, MaxLoops, this.ClusteringPanelChart, this.jTable1, jLabel4, jButton2, jTabbedPane, DistanceType);
            thread.start();
        } else if (this.jRadioButtonMenuItemEM.isSelected()) {
            Thread thread = new ChartThread(CONST.EM_KMEANS, this.VP, K, MaxLoops, this.ClusteringPanelChart, this.jTable1, jLabel4, jButton2, jTabbedPane, DistanceType);
            thread.start();
        } else if (this.jRadioButtonMenuItemKMedoids.isSelected()) {
            Thread thread = new ChartThread(CONST.K_MEDOIDS, this.VP, K, MaxLoops, this.ClusteringPanelChart, this.jTable1, jLabel4, jButton2, jTabbedPane, DistanceType);
            thread.start();
        }
    }//GEN-LAST:event_jButtonAnalysisActionPerformed

    private void jMenuItemAboutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItemAboutActionPerformed
        // TODO add your handling code here:
        AboutJDialog aboutJDialog = new AboutJDialog(this, true);
        Point O = new Point();
        O.setLocation(this.getLocation().x, this.getLocation().y);
        O.move(this.getWidth()/2 - aboutJDialog.getWidth()/2, this.getHeight()/2 - aboutJDialog.getHeight()/2);
        aboutJDialog.setLocation(O);
        aboutJDialog.setVisible(true);
    }//GEN-LAST:event_jMenuItemAboutActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private org.math.plot.Plot3DPanel ClusteringPanelChart;
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.ButtonGroup buttonGroup2;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButtonAnalysis;
    private javax.swing.JButton jButtonBrowse;
    private javax.swing.JButton jButtonTestFile;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel12;
    private javax.swing.JLabel jLabel1DistanceFormula;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabelDistanceMeasureDiscription;
    private javax.swing.JLabel jLabelNofO;
    private javax.swing.JLabel jLabelNumOfOName;
    private javax.swing.JLabel jLabelSizeOfFileName;
    private javax.swing.JLabel jLabelSizeofF;
    private javax.swing.JLabel jLabelStatus;
    private javax.swing.JMenu jMenuAlgorithm;
    private javax.swing.JMenuBar jMenuBar;
    private javax.swing.JMenu jMenuHelp;
    private javax.swing.JMenuItem jMenuItemAbout;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanelPerformance;
    private javax.swing.JPanel jPanelSpecification;
    private javax.swing.JProgressBar jProgressBarTestFile;
    private javax.swing.JRadioButton jRadioButtonEuclidean;
    private javax.swing.JRadioButton jRadioButtonManhattan;
    private javax.swing.JRadioButtonMenuItem jRadioButtonMenuItemBasicKMeans;
    private javax.swing.JRadioButtonMenuItem jRadioButtonMenuItemBisectingKMeans;
    private javax.swing.JRadioButtonMenuItem jRadioButtonMenuItemEM;
    private javax.swing.JRadioButtonMenuItem jRadioButtonMenuItemKMedoids;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JPopupMenu.Separator jSeparatorAlgorithm;
    private javax.swing.JPopupMenu.Separator jSeparatorHelp;
    private javax.swing.JTabbedPane jTabbedPane;
    private javax.swing.JTable jTable1;
    private javax.swing.JTextField jTextFieldClusterNumber;
    private javax.swing.JTextField jTextFieldFileChoice;
    private javax.swing.JTextField jTextFieldIterations;
    // End of variables declaration//GEN-END:variables

    public void actionPerformed(ActionEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
